//假设现在有两个生产宝马和奔驰的工厂
//假设一个车只由车身和车轮组成
//1.定义抽象产品方法
//车身的抽象方法
class AbstractCarBody{
    constructor(brand){
        //品牌名称
        if(!brand) throw new Error('必须传入品牌名称')
        this.brand = brand
        if(new.target == AbstractCarBody){
            throw new Error('不能创建抽象类 AbstractCarBody')
        }
    }
    CarBody(){
        throw new Error("你必须实现CarBody方法")
    }
}
//车轮的抽象方法
class AbstractWheel{
    constructor(brand){
         //品牌名称
         if(!brand) throw new Error('必须传入品牌名称')
            this.brand = brand
            if(new.target == AbstractWheel){
                throw new Error('不能创建抽象类 AbstractWheel')
            }
    }
    wheel(){
        throw new Error("你必须实现wheel方法")
    }
}

//2.抽象产品方法具体实现
class BMWCarBody extends AbstractCarBody{
    constructor(color){
        super('BMW')
        this.color = color

    }
    CarBody(){
        return `我的${this.brand}的车身，我的颜色是${this.color}`
    }
}
class BenzCarBody extends AbstractCarBody{
    constructor(color){
        super('Benz')
        this.color = color
    } 
    CarBody(){
        return `我是${this.brand}的车身，我的颜色是${this.color}`
    }
}
class BMWWheel extends AbstractWheel{
    constructor(color){
        super('BMW')
        this.color = color
    }
    wheel(){
        return `我是${this.brand}的轮子，我的颜色是${this.color}`
    }
}
class BenzWheel extends AbstractWheel{
    constructor(color){
        super('Benz')
        this.color = color
    }
    wheel(){
        return `我是${this.brand}的轮子，我的颜色是${this.color}`
    }
}

//3.抽象工厂
class AbstractFactory{
     constructor(){
        if(!new.target == AbstractFactory)throw new Error('不能创建 AbstractFactory 类')
     }
    createProduct(type){
      switch(type){
        case 'CarBody':return this.createCarBody()
        case 'wheel' : return this.createWheel()
        default:throw new Error('参数错误')
      }  
    }
    createCarBody(){
        throw new Error('createCarBody 方法必须被重写')
    }
    createWheel(){
        throw new Error('createWheel 方法必须被重写')
    }
    assemble(){
        throw new Error('assemble 方法必须被重写')
    }
}
//4.具体工厂实现
class BMWFactory extends AbstractFactory{
    createCarBody(){
        return new BMWCarBody('黑色')
    }
    createWheel(){
        return new BMWWheel('蓝色')
    }
    assemble(){
        this.CarBody=this.createCarBody()
        this.wheel=this.createWheel()
        return this.CarBody.CarBody()+this.wheel.wheel()
    }

}

class BenzFactory extends AbstractFactory{
    
    createCarBody(){
        return new BenzCarBody('粉色')
    }
    createWheel(){
        return new BenzWheel('紫色')
    }
    assemble(){
        this.CarBody=this.createCarBody()
        this.wheel=this.createWheel()
        return this.CarBody.CarBody()+this.wheel.wheel()
    }
}
//5.客户端
function clientCode(factory){
    factory.createCarBody()
    factory.createWheel()
    console.log(factory.assemble());
}
const bmwFactory = new BMWFactory()
const benzFactory = new BenzFactory()
clientCode(bmwFactory)
clientCode(benzFactory)
//需要一个奔驰的轮胎 
const a = benzFactory.createProduct('wheel')
console.log(a.wheel());